/**
 * 数据点选择框
 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Select, Input, Icon } from 'antd';

const Option = Select.Option;

const styles = {
	select: {
		width: '14em',
		marginRight: '0.5em'
	},
	input: {
		width: '8em',
		marginRight: '0.5em'
	},
	icon: {
		fontSize: '18px',
		verticalAlign: 'sub',
		marginRight: '0.5em'
	},
	item: {
		margin: '0.5em 0'
	}
};

const opts = [
	{ value: '>', name: '>' },
	{ value: '>=', name: '≥' },
	{ value: '=', name: '=' },
	{ value: '!=', name: '≠' },
	{ value: '<', name: '<' },
	{ value: '<=', name: '≤' },
];

class CommandEdit extends Component {
	constructor(props, context) {
		super(props, context);
		this.state = {
			dataPoint: this.filterDataPoint(props),
			// refDataPoint: this.filterDataPoint(props)[0].identityName,
			refDataPoint: '',
		};
		if (props.needInput) {
			this.state.value = this.objToArr(props.value);
		} else {
			this.state.value = [{ key: '', value: '' }];
		}
	}

	static defaultProps = {
		needInput: true,
		needMulti: true,
	}

	componentWillReceiveProps(nextProps) {
		if (!this.changed) this.setState({ value: this.objToArr(nextProps.value) });
		if (nextProps.dataPoint !== this.props.dataPoint) {
			this.setState({
				dataPoint: this.filterDataPoint(nextProps)
			});
		}
	}

	getValue() {
		const { type, needInput = true } = this.props;
		const { value, refDataPoint } = this.state;
		if (!needInput) {
			return refDataPoint;
		}
		return value.reduce((p, v) => {
			const valueType = typeof v.value;
			if (v.key && (v.value || valueType === 'boolean' || valueType === 'number')) {
				if (type === 'status') {
					p[v.key] = {
						operator: v.operator || '=',
						value: v.value
					};
				} else {
					p[v.key] = v.value;
				}
			}
			return p;
		}, {});
	}

	filterDataPoint(props) {
		const { dataPoint, readWriteType = 'status_writable' } = props;
		if (readWriteType) {
			return props.dataPoint.filter(d => d.readWriteType === readWriteType);
		} else {
			return dataPoint;
		}
	}

	objToArr(obj) {
		const { type } = this.props;
		const { dataPoint } = this.state;
		if (!obj || !Object.keys(obj).length) {
			const key = dataPoint.length ? dataPoint[0].identityName : '';
			return [{ key, value: '' }];
		}
		if (type === 'status') {
			return Object.keys(obj).map(key => ({ key, ...obj[key] }));
		} else {
			return Object.keys(obj).map(key => ({ key, value: obj[key] }));
		}
	}

	select = (key, index) => {
		const { value } = this.state;
		const { needInput = true } = this.props;
		if (!needInput) {
			this.setState({
				refDataPoint: key,
			});
		}
		this.setState({
			value: value.map((v, i) => index === i ? { key, value: '' } : v)
		});
		this.changed = true;
	}

	valueChange = (val, index, dataType, name = 'value') => {
		const { value } = this.state;
		if (dataType && dataType.includes('uint')) val = parseFloat(val);
		this.setState({
			value: value.map((v, i) => index === i ? { ...v, [name]: val } : v)
		});
		this.changed = true;
	}

	add = () => {
		const { value } = this.state;
		this.setState({ value: value.concat({ key: '', value: '' }) });
		this.changed = true;
	}

	minus = index => {
		const { value } = this.state;
		this.setState({ value: value.filter((v, i) => i !== index) });
		this.changed = true;
	}

	renderInput({ key, value, operator }, i) {
		const { type } = this.props;
		const { dataPoint } = this.state;
		const point = dataPoint.find(p => p.identityName === key);

		let input = <Input value={value} onChange={e => this.valueChange(e.target.value, i)} style={styles.input} />;

		if (point) {
			const { dataType, valueLimit } = point;
			input = <Input value={value} onChange={e => this.valueChange(e.target.value, i, dataType)} style={styles.input} />;
			let values = valueLimit;
			if (dataType === 'enum') {
				values = `["${valueLimit.slice(1, valueLimit.length - 1).replace(/,\s/g, '", "')}"]`;
			}
			values = JSON.parse(values);
			if (dataType === 'bool' && type === 'status') {
				values = values.map(v => ({ name: v, value: v * 1 }));
				input = (
					<Select value={value} style={styles.input} onChange={v => this.valueChange(v, i)}>
						{values.map(v => <Option value={v.value}>{`${v.name}`}</Option>)}
					</Select>
				);
			} else if (dataType === 'bool' || dataType === 'enum') {
				input = (
					<Select value={value} style={styles.input} onChange={v => this.valueChange(v, i)}>
						{values.map(v => <Option value={v}>{`${v}`}</Option>)}
					</Select>
				);
			}

			if (type === 'status' && (dataType.includes('uint') || dataType === 'binary')) {
				input = [input];
				input.unshift(
					<Select value={operator} style={styles.input} onChange={v => this.valueChange(v, i, 'operator', 'operator')}>
						{opts.map(v => <Option value={v.value}>{v.name}</Option>)}
					</Select>
				);
			}
		}
		return input;
	}

	render() {
		const { dataPoint } = this.state;
		const { value } = this.state;
		const { needInput = true, needMulti = true } = this.props;
		const options = dataPoint.map(d => <Option value={d.identityName}>{d.identityName}</Option>);
		return (
			<div>
				{
					value.map((v, i) => (
						<div key={i} style={styles.item}>
							<Select style={styles.select} onChange={key => this.select(key, i)} value={v.key}>
								{needInput ? options : [<Option value="">置空</Option>, ...options]}
							</Select>
							{needInput && this.renderInput(v, i)}
							{
								(value.length !== 1 && needMulti)
									? <Icon type="minus-circle-o" style={styles.icon} className="cursor" onClick={() => this.minus(i)} />
									: null
							}
							{
								(i === value.length - 1 && needMulti)
									? <Icon type="plus-circle-o" style={styles.icon} className="cursor" onClick={this.add} />
									: null
							}
						</div>
					))
				}
			</div>
		);
	}
}

CommandEdit.propTypes = {

};

export default CommandEdit;
